library(readxl)
library(dplyr)
library(stringr)
library(purrr)
library(tm)
library(SnowballC)
library(syuzhet)
library(viridis)
library(plotly)
library(readxl)
# Run this library to read excel or csv file. If you do not have it then install the package by using a function call install.packages("readxl")#.
# If you're reading from a CSV or Excel file, you would use something like read.csv() or read_excel() to load your data to a data frame
All_Tweets <- read.csv("C:/Users/91992/OneDrive/Desktop/GGU/R projects/justdoit_tweets_colin.csv", header = TRUE)
# Prepare the data by selecting relevant columns and cleaning text
All_Selected_Tweets <- All_Tweets %>%
select(tweet_created_at, tweet_favorite_count, tweet_full_text, tweet_id,
tweet_in_reply_to_screen_name, tweet_in_reply_to_status_id, tweet_retweet_count,
user_favourites_count, user_followers_count, user_id, user_location,
user_location) %>%
mutate(tweet_full_text = str_remove_all(tweet_full_text, "–|’|—|“|”|-|&|https://[^\\s]+"),
tweet_full_text = tolower(tweet_full_text),
tweet_full_text = removePunctuation(tweet_full_text),
tweet_full_text = stripWhitespace(tweet_full_text),
tweet_full_text = wordStem(tweet_full_text))
# Sentiment analysis
syuzhet_score <- get_sentiment(All_Selected_Tweets$tweet_full_text, method = "syuzhet")
nrc_score <- get_sentiment(All_Selected_Tweets$tweet_full_text, method = "nrc")
# Combine scores and normalize
Tweet_Threads_Analysis <- cbind(All_Selected_Tweets, syuzhet_score, nrc_score) %>%
mutate(Syuzhet = sign(syuzhet_score),
NRC = sign(nrc_score))
# Emotions and Sentiments visualization
nrc_sentiment <- get_nrc_sentiment(All_Selected_Tweets$tweet_full_text)
sentisum <- colSums(nrc_sentiment)
interactive_bar <- plot_ly(x = names(sentisum), y = sentisum, type = 'bar',
marker = list(color = viridis::viridis(length(names(sentisum)), option = "D"))) %>%
layout(title = 'Emotions and Sentiments', xaxis = list(title = ''), yaxis = list(title = 'Count'))
# Display the plot
interactive_bar
# View the negative comment basis syuzhet score
min(Tweet_Threads_Analysis$Syuzhet)
[1] -1
minScore <- which(Tweet_Threads_Analysis$syuzhet==min(Tweet_Threads_Analysis$Syuzhet))
minScore
[1] 59 139 153 165 224 313 315 328 387 390 434 493 546 655 680 779 831 999
[19] 1047 1070 1087 1102 1119 1124 1157 1163 1190 1195 1253 1320 1428 1486 1550 1582 1619 1682
[37] 1684 1699 1772 1796 1799 1809 1854 1912 1946 1982 2005 2057 2115 2218 2274 2409 2412 2461
[55] 2598 2696 2780 2808 3008 3142 3166 3169 3173 3203 3507 3643 3645 3670 3725 3726 3727 3764
[73] 3814 3852 3927 3965 3994 4088 4103 4219 4289 4312 4345 4386 4501 4584 4607 4664 4711 5083
All_Selected_Tweets[minScore]
Error in `[.data.frame`(All_Selected_Tweets, minScore) :
undefined columns selected
# Displaying the tweets with the minimum Syuzhet score and limiting to 10 tweets
tweets_with_min_syuzhet <- All_Selected_Tweets$tweet_full_text[minScore][1:10]
# To print the tweets
print(tweets_with_min_syuzhet)
[1] "justdoit nike took a knee for kaepernick outrage ensues were you surprised "
[2] "realdonaldtrump they are thinking about the greatness in every single one something that you are incapable of comprehending too bad justdoit 🕡🕡🅡🅡🕡🕡🥡"
[3] "istandwithice icegov justdoit bringiton maga americafirst illegalaliens are criminals buildthatwallnow buildthewall secureourborders borderpatrol waityourturn vote red kag "
[4] "calling a dream crazy its not an insult its a compliment justdoit"
[5] "believe in something even if it means sacrificing every motherfucker in the jungle nike justdoit predator "
[6] "wtf people like gillum and other socialistsdems are why we cannot progress due to digging 150 yrs in the past to paint everyone racists and use black people from physical slavery to mental slavery thedemocrats never change and justdoit "
[7] "bet these are causing havoc for all those in the boycottnike side of thingsthe flag on nikes justdoit kaepernick "
[8] "sometimes you gotta knock a bitch out🝥🍥♀️justdoit nik"
[9] "bigbrothergod1 don43pmdon amen colin didnt sacrifice anything he had a contract and turned down two offers he didnt sacrifice rather than justdoit he just quit and hes still a millionaire and a pouty whiny leftist"
[10] "weve seen the outrage on social media on nikes move to use colin kaepernick as a spokesperson for justdoit according to retail experts at brp despite the backlash its a calculated risk but the ad will only do good things more here nike "
# View the positive comment basis syuzhet score
max(Tweet_Threads_Analysis$Syuzhet)
[1] 1
maxScore <- which(Tweet_Threads_Analysis$syuzhet==max(Tweet_Threads_Analysis$Syuzhet))
maxScore
[1] 38 160 198 200 221 229 243 252 277 285 326 346 359 381 382 458 467 470
[19] 508 566 593 599 647 649 659 728 768 855 889 917 934 936 968 1003 1035 1092
[37] 1093 1098 1114 1118 1143 1159 1167 1185 1188 1201 1233 1254 1313 1343 1369 1382 1447 1450
[55] 1462 1477 1496 1535 1572 1587 1618 1673 1692 1703 1715 1726 1785 1837 1851 1877 1888 1997
[73] 2067 2077 2096 2169 2198 2225 2257 2346 2372 2433 2449 2452 2465 2579 2586 2621 2648 2676
[91] 2706 2709 2729 2784 2795 2799 2813 2908 2952 2982 3028 3102 3155 3185 3188 3196 3211 3238
[109] 3244 3257 3311 3336 3368 3376 3386 3409 3449 3474 3475 3487 3488 3502 3504 3533 3536 3581
[127] 3590 3632 3682 3684 3688 3710 3772 3777 3797 3874 3902 3920 3936 4001 4018 4034 4078 4116
[145] 4193 4242 4353 4354 4367 4374 4378 4389 4406 4423 4432 4476 4528 4615 4637 4653 4682 4709
[163] 4784 4806 4816 4880 4947 4968 4978 4991 4995 5003 5059
All_Selected_Tweets[maxScore]
Error in `[.data.frame`(All_Selected_Tweets, maxScore) :
undefined columns selected
# Displaying the tweets with the maximum Syuzhet score and limiting to 10 tweets
tweets_with_max_syuzhet <- All_Selected_Tweets$tweet_full_text[maxScore][1:10]
# To print the tweets
print(tweets_with_max_syuzhet)
[1] "realdonaldtrump its clear why you kim respect each other so muchdonaldlovesdictators takeaknee colinkaepernick nike justdoit fightfascism "
[2] "im sure imchelseagreen will have her spot in a wwe ring soon after listening to eandcpodcastofawesomeness im even more inspired by her will to justdoit this woman is amazing 🐳🀳🐳🀳🐳🀳🐳🀳🐳🀳❤️❤️❤️❤️❤️❤️day1 fan riding with imchelseagreen all the wai"
[3] "september 19th interest free newmusic fridaymotivation justdoit album westcoast nyc vancouver "
[4] "omg woo me i just loved being wooed me fridayfeeling bigfacts justdoit uapb21 retweeet share listenbetter quote puregoals teamfollowback waitonit uapb21 naturalwoman afro "
[5] "botblocking is therapeutic justdoit "
[6] "clear cut winner with the justdoit memes therock 🥡 "
[7] "open mic 🅮 performed real recognize real last night and had a good time doing it ybm justdoit dowhatmakesyouhappy ybm "
[8] "dont just buy shoes buy stock thelifeeengineer investlikealady livelikeaboss justdoit yesterday i purchased nike stock for all my children my nephew teach them ownership "
[9] "justdoit nikes stance on social justice by thereclaimed "
[10] "alternet why focus on wackiness trump is a threat to the constitution let comedians like kathygriffin make fun of him all other reporting should be on how do we get him out of office🜴🌴🌴justdoit impeachtrump 25amendmentnow "
library(ggplot2)
# Create ggplot histogram
p <- ggplot(Tweet_Threads_Analysis, aes(x = Syuzhet)) + # Ensure the column name matches your dataframe
geom_histogram(bins = 5, fill = "purple", color = "white") +
labs(title = "Distribution of Sentiment Scores", x = "Sentiment Score", y = "Frequency")
library(plotly)
# Convert to Plotly for interactivity
p_interactive <- ggplotly(p)
# Display the interactive plot
p_interactive
# Calculate average sentiment for each state
state_sentiment <- Tweet_Threads_Analysis %>%
group_by(user_location) %>%
summarise(average_sentiment = mean(syuzhet_score, na.rm = TRUE)) %>%
ungroup()
# Top 5 states with the highest average sentiment
top_5_states <- state_sentiment %>%
top_n(5, average_sentiment)
# Bottom 5 states with the lowest average sentiment
bottom_5_states <- state_sentiment %>%
top_n(-5, average_sentiment)
# Top 5 states with the highest average sentiment
top_5_states <- state_sentiment %>%
slice_max(order_by = average_sentiment, n = 5)
print(top_5_states, "Top 5 States by Average Sentiment")
# Bottom 5 states with the lowest average sentiment
bottom_5_states <- state_sentiment %>%
slice_min(order_by = average_sentiment, n = 5)
print(bottom_5_states, "Bottom 5 States by Average Sentiment")
# The dataset would require cleaning. Read the file thouroghly and clean/impute data
Cleaned_Tweets <- read.csv("C:/Users/91992/OneDrive/Desktop/GGU/R projects/Nike_Colin_Tweets_Cleaned.csv", header = TRUE)
# Prepare the data by selecting relevant columns and cleaning text
All_Cleaned_Tweets <- Cleaned_Tweets %>%
select(tweet_created_at, tweet_favorite_count, tweet_full_text, tweet_id,
tweet_retweet_count, user_favourites_count, user_followers_count, user_id, user_location,
user_location_us, Sentiment) %>%
mutate(tweet_full_text = str_remove_all(tweet_full_text, "–|’|—|“|”|-|&|https://[^\\s]+"),
tweet_full_text = tolower(tweet_full_text),
tweet_full_text = removePunctuation(tweet_full_text),
tweet_full_text = stripWhitespace(tweet_full_text),
tweet_full_text = wordStem(tweet_full_text))
# Calculate average sentiment for each state
state_sentiment <- All_Cleaned_Tweets %>%
group_by(user_location_us) %>%
summarise(average_sentiment = mean(Sentiment, na.rm = TRUE)) %>%
# Arrange data in descending order of average_sentiment
arrange(desc(average_sentiment))
# Top 5 states with the highest average sentiment
top_5_states <- state_sentiment %>%
slice_max(order_by = average_sentiment, n = 5)
print(top_5_states, "Top 5 States by Average Sentiment")
# Bottom 5 states with the lowest average sentiment
bottom_5_states <- state_sentiment %>%
slice_min(order_by = average_sentiment, n = 5)
print(bottom_5_states, "Bottom 5 States by Average Sentiment")
# Let us correlate with the sales for Nike acorss North America with the sales dataset for 2020-2021
Nike_sales_data <- read.csv("C:/Users/91992/OneDrive/Desktop/GGU/R projects/Nike_Sales_US.csv", header = TRUE)
# Define the list of states you're interested in
top_5_states_sales <- c("Montana", "North Dakota", "Wyoming", "Delaware", "Missouri")
# Summarize the final sales count for the selected states
final_sales_top_selected_states <- Nike_sales_data %>%
filter(State %in% top_5_states_sales) %>%
group_by(State) %>%
summarise(TotalSalesCount = sum(Total.Sales, na.rm = TRUE)) %>%
ungroup() # Optional, to remove the grouping
# Display the result
print(final_sales_top_selected_states)
# Define the list of states you're interested in
bottom_5_states_sales <- c("Oklahoma", "West Virginia", "Alaska", "Nebraska", "Mississippi")
# Summarize the final sales count for the selected states
final_sales_bottom_selected_states <- Nike_sales_data %>%
filter(State %in% bottom_5_states_sales) %>%
group_by(State) %>%
summarise(TotalSalesCount = sum(Total.Sales, na.rm = TRUE)) %>%
ungroup() # Optional, to remove the grouping
# Display the result
print(final_sales_bottom_selected_states)
# normalize sentiment score
All_Cleaned_Tweets <- All_Cleaned_Tweets %>%
mutate(Normalized_Syuzhet = sign(Sentiment))
# Apply the function to positive and negative tweets
positive_tweets <- All_Cleaned_Tweets[All_Cleaned_Tweets$Normalized_Syuzhet > 0, ]
negative_tweets <- All_Cleaned_Tweets[All_Cleaned_Tweets$Normalized_Syuzhet < 0, ]
library(dplyr)
# For Positive Tweets
top_5_positive_states <- positive_tweets %>%
group_by(user_location_us) %>%
summarise(PositiveTweetCount = n()) %>%
arrange(desc(PositiveTweetCount)) %>%
slice_head(n = 5)
# For Negative Tweets
top_5_negative_states <- negative_tweets %>%
group_by(user_location_us) %>%
summarise(NegativeTweetCount = n()) %>%
arrange(desc(NegativeTweetCount)) %>%
slice_head(n = 5)
# Print the results
print("Top 5 States with Highest Positive Tweets:")
[1] "Top 5 States with Highest Positive Tweets:"
print(top_5_positive_states)
print("Top 5 States with Highest Negative Tweets:")
[1] "Top 5 States with Highest Negative Tweets:"
print(top_5_negative_states)
# Assuming the states are stored in a column named 'State' in top_5_positive_states and top_5_negative_states data frames
top_5_positive_states_list <- top_5_positive_states$user_location_us
top_5_negative_states_list <- top_5_negative_states$user_location_us
# Filter tweets from these top 5 states
positive_tweets_top5 <- positive_tweets %>%
filter(user_location_us %in% top_5_positive_states_list)
negative_tweets_top5 <- negative_tweets %>%
filter(user_location_us %in% top_5_negative_states_list)
library(tidytext)
# Tokenize positive tweets and calculate word frequencies
positive_word_freq <- positive_tweets_top5 %>%
unnest_tokens(word, tweet_full_text) %>%
count(word, sort = TRUE)
# Tokenize negative tweets and calculate word frequencies
negative_word_freq <- negative_tweets_top5 %>%
unnest_tokens(word, tweet_full_text) %>%
count(word, sort = TRUE)
data("stop_words")
positive_word_freq <- positive_word_freq %>%
anti_join(stop_words, by = "word")
negative_word_freq <- negative_word_freq %>%
anti_join(stop_words, by = "word")
# Adjust N as needed
N <- 10
head(positive_word_freq, N)
head(negative_word_freq, N)
library(dplyr)
# Assuming N = 10
N <- 10
top_positive_word_freq <- positive_word_freq %>%
head(N)
top_negative_word_freq <- negative_word_freq %>%
head(N)
library(ggplot2)
# Plot for positive word frequencies
ggplot(top_positive_word_freq, aes(x = reorder(word, n), y = n)) +
geom_col(fill = "dodgerblue") +
geom_text(aes(label = n), position = position_dodge(width = 0.9), vjust = -0.25, size = 3.5) +
coord_flip() +
labs(title = "Top 10 Word Frequencies in Positive Tweets",
x = "Word",
y = "Frequency") +
theme_minimal()

# Plot for negative word frequencies
ggplot(top_negative_word_freq, aes(x = reorder(word, n), y = n)) +
geom_col(fill = "firebrick") +
geom_text(aes(label = n), position = position_dodge(width = 0.9), vjust = -0.25, size = 3.5) +
coord_flip() +
labs(title = "Top 10 Word Frequencies in Negative Tweets",
x = "Word",
y = "Frequency") +
theme_minimal()

LS0tDQp0aXRsZTogIk5pa2UgQ29saW4gS2FlcGVybmljayBTZW50aW1lbnQgQW5hbHlzaXMiDQpvdXRwdXQ6DQogIGh0bWxfZG9jdW1lbnQ6IGRlZmF1bHQNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHhsKQ0KbGlicmFyeShkcGx5cikNCmxpYnJhcnkoc3RyaW5ncikNCmxpYnJhcnkocHVycnIpDQpsaWJyYXJ5KHRtKQ0KbGlicmFyeShTbm93YmFsbEMpDQpsaWJyYXJ5KHN5dXpoZXQpDQpsaWJyYXJ5KHZpcmlkaXMpDQpsaWJyYXJ5KHBsb3RseSkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkocmVhZHhsKQ0KDQojIFJ1biB0aGlzIGxpYnJhcnkgdG8gcmVhZCBleGNlbCBvciBjc3YgZmlsZS4gSWYgeW91IGRvIG5vdCBoYXZlIGl0IHRoZW4gaW5zdGFsbCB0aGUgcGFja2FnZSBieSB1c2luZyBhIGZ1bmN0aW9uIGNhbGwgaW5zdGFsbC5wYWNrYWdlcygicmVhZHhsIikjLiANCmBgYA0KDQpgYGB7cn0NCiMgSWYgeW91J3JlIHJlYWRpbmcgZnJvbSBhIENTViBvciBFeGNlbCBmaWxlLCB5b3Ugd291bGQgdXNlIHNvbWV0aGluZyBsaWtlIHJlYWQuY3N2KCkgb3IgcmVhZF9leGNlbCgpIHRvIGxvYWQgeW91ciBkYXRhIHRvIGEgZGF0YSBmcmFtZQ0KDQpBbGxfVHdlZXRzIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy85MTk5Mi9PbmVEcml2ZS9EZXNrdG9wL0dHVS9SIHByb2plY3RzL2p1c3Rkb2l0X3R3ZWV0c19jb2xpbi5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KIyBQcmVwYXJlIHRoZSBkYXRhIGJ5IHNlbGVjdGluZyByZWxldmFudCBjb2x1bW5zIGFuZCBjbGVhbmluZyB0ZXh0DQpBbGxfU2VsZWN0ZWRfVHdlZXRzIDwtIEFsbF9Ud2VldHMgJT4lIA0KICBzZWxlY3QodHdlZXRfY3JlYXRlZF9hdCwgdHdlZXRfZmF2b3JpdGVfY291bnQsIHR3ZWV0X2Z1bGxfdGV4dCwgdHdlZXRfaWQsDQogICAgICAgICB0d2VldF9pbl9yZXBseV90b19zY3JlZW5fbmFtZSwgdHdlZXRfaW5fcmVwbHlfdG9fc3RhdHVzX2lkLCB0d2VldF9yZXR3ZWV0X2NvdW50LA0KICAgICAgICAgdXNlcl9mYXZvdXJpdGVzX2NvdW50LCB1c2VyX2ZvbGxvd2Vyc19jb3VudCwgdXNlcl9pZCwgdXNlcl9sb2NhdGlvbiwNCiAgICAgICAgIHVzZXJfbG9jYXRpb24pICU+JQ0KICBtdXRhdGUodHdlZXRfZnVsbF90ZXh0ID0gc3RyX3JlbW92ZV9hbGwodHdlZXRfZnVsbF90ZXh0LCAi4oCTfOKAmXzigJR84oCcfOKAnXwtfCZhbXB8aHR0cHM6Ly9bXlxcc10rIiksDQogICAgICAgICB0d2VldF9mdWxsX3RleHQgPSB0b2xvd2VyKHR3ZWV0X2Z1bGxfdGV4dCksDQogICAgICAgICB0d2VldF9mdWxsX3RleHQgPSByZW1vdmVQdW5jdHVhdGlvbih0d2VldF9mdWxsX3RleHQpLA0KICAgICAgICAgdHdlZXRfZnVsbF90ZXh0ID0gc3RyaXBXaGl0ZXNwYWNlKHR3ZWV0X2Z1bGxfdGV4dCksDQogICAgICAgICB0d2VldF9mdWxsX3RleHQgPSB3b3JkU3RlbSh0d2VldF9mdWxsX3RleHQpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBTZW50aW1lbnQgYW5hbHlzaXMNCnN5dXpoZXRfc2NvcmUgPC0gZ2V0X3NlbnRpbWVudChBbGxfU2VsZWN0ZWRfVHdlZXRzJHR3ZWV0X2Z1bGxfdGV4dCwgbWV0aG9kID0gInN5dXpoZXQiKQ0KbnJjX3Njb3JlIDwtIGdldF9zZW50aW1lbnQoQWxsX1NlbGVjdGVkX1R3ZWV0cyR0d2VldF9mdWxsX3RleHQsIG1ldGhvZCA9ICJucmMiKQ0KYGBgDQoNCmBgYHtyfQ0KIyBDb21iaW5lIHNjb3JlcyBhbmQgbm9ybWFsaXplDQpUd2VldF9UaHJlYWRzX0FuYWx5c2lzIDwtIGNiaW5kKEFsbF9TZWxlY3RlZF9Ud2VldHMsIHN5dXpoZXRfc2NvcmUsIG5yY19zY29yZSkgJT4lDQogIG11dGF0ZShTeXV6aGV0ID0gc2lnbihzeXV6aGV0X3Njb3JlKSwNCiAgICAgICAgIE5SQyA9IHNpZ24obnJjX3Njb3JlKSkNCmBgYA0KDQpgYGB7cn0NCiMgRW1vdGlvbnMgYW5kIFNlbnRpbWVudHMgdmlzdWFsaXphdGlvbg0KbnJjX3NlbnRpbWVudCA8LSBnZXRfbnJjX3NlbnRpbWVudChBbGxfU2VsZWN0ZWRfVHdlZXRzJHR3ZWV0X2Z1bGxfdGV4dCkNCnNlbnRpc3VtIDwtIGNvbFN1bXMobnJjX3NlbnRpbWVudCkNCmludGVyYWN0aXZlX2JhciA8LSBwbG90X2x5KHggPSBuYW1lcyhzZW50aXN1bSksIHkgPSBzZW50aXN1bSwgdHlwZSA9ICdiYXInLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgIG1hcmtlciA9IGxpc3QoY29sb3IgPSB2aXJpZGlzOjp2aXJpZGlzKGxlbmd0aChuYW1lcyhzZW50aXN1bSkpLCBvcHRpb24gPSAiRCIpKSkgJT4lDQogIGxheW91dCh0aXRsZSA9ICdFbW90aW9ucyBhbmQgU2VudGltZW50cycsIHhheGlzID0gbGlzdCh0aXRsZSA9ICcnKSwgeWF4aXMgPSBsaXN0KHRpdGxlID0gJ0NvdW50JykpDQpgYGANCg0KYGBge3J9DQojIERpc3BsYXkgdGhlIHBsb3QNCmludGVyYWN0aXZlX2Jhcg0KYGBgDQoNCmBgYHtyfQ0KIyBWaWV3IHRoZSBuZWdhdGl2ZSBjb21tZW50IGJhc2lzIHN5dXpoZXQgc2NvcmUNCg0KbWluKFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMkU3l1emhldCkNCm1pblNjb3JlIDwtIHdoaWNoKFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMkc3l1emhldD09bWluKFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMkU3l1emhldCkpDQptaW5TY29yZQ0KQWxsX1NlbGVjdGVkX1R3ZWV0c3NbbWluU2NvcmVdDQpgYGANCg0KYGBge3J9DQojIERpc3BsYXlpbmcgdGhlIHR3ZWV0cyB3aXRoIHRoZSBtaW5pbXVtIFN5dXpoZXQgc2NvcmUgYW5kIGxpbWl0aW5nIHRvIDEwIHR3ZWV0cw0KdHdlZXRzX3dpdGhfbWluX3N5dXpoZXQgPC0gQWxsX1NlbGVjdGVkX1R3ZWV0cyR0d2VldF9mdWxsX3RleHRbbWluU2NvcmVdWzE6MTBdDQoNCiMgVG8gcHJpbnQgdGhlIHR3ZWV0cw0KcHJpbnQodHdlZXRzX3dpdGhfbWluX3N5dXpoZXQpDQpgYGANCmBgYHtyfQ0KIyBWaWV3IHRoZSBwb3NpdGl2ZSBjb21tZW50IGJhc2lzIHN5dXpoZXQgc2NvcmUNCg0KbWF4KFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMkU3l1emhldCkNCm1heFNjb3JlIDwtIHdoaWNoKFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMkc3l1emhldD09bWF4KFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMkU3l1emhldCkpDQptYXhTY29yZQ0KQWxsX1NlbGVjdGVkX1R3ZWV0c1ttYXhTY29yZV0NCmBgYA0KDQpgYGB7cn0NCiMgRGlzcGxheWluZyB0aGUgdHdlZXRzIHdpdGggdGhlIG1heGltdW0gU3l1emhldCBzY29yZSBhbmQgbGltaXRpbmcgdG8gMTAgdHdlZXRzDQp0d2VldHNfd2l0aF9tYXhfc3l1emhldCA8LSBBbGxfU2VsZWN0ZWRfVHdlZXRzJHR3ZWV0X2Z1bGxfdGV4dFttYXhTY29yZV1bMToxMF0NCg0KIyBUbyBwcmludCB0aGUgdHdlZXRzDQpwcmludCh0d2VldHNfd2l0aF9tYXhfc3l1emhldCkNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgQ3JlYXRlIGdncGxvdCBoaXN0b2dyYW0NCnAgPC0gZ2dwbG90KFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMsIGFlcyh4ID0gU3l1emhldCkpICsgICMgRW5zdXJlIHRoZSBjb2x1bW4gbmFtZSBtYXRjaGVzIHlvdXIgZGF0YWZyYW1lDQogIGdlb21faGlzdG9ncmFtKGJpbnMgPSA1LCBmaWxsID0gInB1cnBsZSIsIGNvbG9yID0gIndoaXRlIikgKw0KICBsYWJzKHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBTZW50aW1lbnQgU2NvcmVzIiwgeCA9ICJTZW50aW1lbnQgU2NvcmUiLCB5ID0gIkZyZXF1ZW5jeSIpDQpgYGANCg0KDQpgYGB7cn0NCmxpYnJhcnkocGxvdGx5KQ0KDQojIENvbnZlcnQgdG8gUGxvdGx5IGZvciBpbnRlcmFjdGl2aXR5DQpwX2ludGVyYWN0aXZlIDwtIGdncGxvdGx5KHApDQoNCiMgRGlzcGxheSB0aGUgaW50ZXJhY3RpdmUgcGxvdA0KcF9pbnRlcmFjdGl2ZQ0KYGBgDQoNCg0KYGBge3J9DQojIENhbGN1bGF0ZSBhdmVyYWdlIHNlbnRpbWVudCBmb3IgZWFjaCBzdGF0ZQ0Kc3RhdGVfc2VudGltZW50IDwtIFR3ZWV0X1RocmVhZHNfQW5hbHlzaXMgJT4lDQogIGdyb3VwX2J5KHVzZXJfbG9jYXRpb24pICU+JQ0KICBzdW1tYXJpc2UoYXZlcmFnZV9zZW50aW1lbnQgPSBtZWFuKHN5dXpoZXRfc2NvcmUsIG5hLnJtID0gVFJVRSkpICU+JQ0KICB1bmdyb3VwKCkNCmBgYA0KDQpgYGB7cn0NCiMgVG9wIDUgc3RhdGVzIHdpdGggdGhlIGhpZ2hlc3QgYXZlcmFnZSBzZW50aW1lbnQNCnRvcF81X3N0YXRlcyA8LSBzdGF0ZV9zZW50aW1lbnQgJT4lDQogIHRvcF9uKDUsIGF2ZXJhZ2Vfc2VudGltZW50KQ0KYGBgDQoNCmBgYHtyfQ0KIyBCb3R0b20gNSBzdGF0ZXMgd2l0aCB0aGUgbG93ZXN0IGF2ZXJhZ2Ugc2VudGltZW50DQpib3R0b21fNV9zdGF0ZXMgPC0gc3RhdGVfc2VudGltZW50ICU+JQ0KICB0b3BfbigtNSwgYXZlcmFnZV9zZW50aW1lbnQpDQpgYGANCg0KYGBge3J9DQojIFRvcCA1IHN0YXRlcyB3aXRoIHRoZSBoaWdoZXN0IGF2ZXJhZ2Ugc2VudGltZW50DQp0b3BfNV9zdGF0ZXMgPC0gc3RhdGVfc2VudGltZW50ICU+JQ0KICBzbGljZV9tYXgob3JkZXJfYnkgPSBhdmVyYWdlX3NlbnRpbWVudCwgbiA9IDUpDQpwcmludCh0b3BfNV9zdGF0ZXMsICJUb3AgNSBTdGF0ZXMgYnkgQXZlcmFnZSBTZW50aW1lbnQiKQ0KDQojIEJvdHRvbSA1IHN0YXRlcyB3aXRoIHRoZSBsb3dlc3QgYXZlcmFnZSBzZW50aW1lbnQNCmJvdHRvbV81X3N0YXRlcyA8LSBzdGF0ZV9zZW50aW1lbnQgJT4lDQogIHNsaWNlX21pbihvcmRlcl9ieSA9IGF2ZXJhZ2Vfc2VudGltZW50LCBuID0gNSkNCnByaW50KGJvdHRvbV81X3N0YXRlcywgIkJvdHRvbSA1IFN0YXRlcyBieSBBdmVyYWdlIFNlbnRpbWVudCIpDQpgYGANCg0KYGBge3J9DQojIFRoZSBkYXRhc2V0IHdvdWxkIHJlcXVpcmUgY2xlYW5pbmcuIFJlYWQgdGhlIGZpbGUgdGhvdXJvZ2hseSBhbmQgY2xlYW4vaW1wdXRlIGRhdGENCg0KQ2xlYW5lZF9Ud2VldHMgPC0gcmVhZC5jc3YoIkM6L1VzZXJzLzkxOTkyL09uZURyaXZlL0Rlc2t0b3AvR0dVL1IgcHJvamVjdHMvTmlrZV9Db2xpbl9Ud2VldHNfQ2xlYW5lZC5jc3YiLCBoZWFkZXIgPSBUUlVFKQ0KYGBgDQoNCmBgYHtyfQ0KIyBQcmVwYXJlIHRoZSBkYXRhIGJ5IHNlbGVjdGluZyByZWxldmFudCBjb2x1bW5zIGFuZCBjbGVhbmluZyB0ZXh0DQpBbGxfQ2xlYW5lZF9Ud2VldHMgPC0gQ2xlYW5lZF9Ud2VldHMgJT4lIA0KICBzZWxlY3QodHdlZXRfY3JlYXRlZF9hdCwgdHdlZXRfZmF2b3JpdGVfY291bnQsIHR3ZWV0X2Z1bGxfdGV4dCwgdHdlZXRfaWQsDQogICAgICAgICB0d2VldF9yZXR3ZWV0X2NvdW50LCB1c2VyX2Zhdm91cml0ZXNfY291bnQsIHVzZXJfZm9sbG93ZXJzX2NvdW50LCB1c2VyX2lkLCB1c2VyX2xvY2F0aW9uLA0KICAgICAgICAgdXNlcl9sb2NhdGlvbl91cywgU2VudGltZW50KSAlPiUNCiAgbXV0YXRlKHR3ZWV0X2Z1bGxfdGV4dCA9IHN0cl9yZW1vdmVfYWxsKHR3ZWV0X2Z1bGxfdGV4dCwgIuKAk3zigJl84oCUfOKAnHzigJ18LXwmYW1wfGh0dHBzOi8vW15cXHNdKyIpLA0KICAgICAgICAgdHdlZXRfZnVsbF90ZXh0ID0gdG9sb3dlcih0d2VldF9mdWxsX3RleHQpLA0KICAgICAgICAgdHdlZXRfZnVsbF90ZXh0ID0gcmVtb3ZlUHVuY3R1YXRpb24odHdlZXRfZnVsbF90ZXh0KSwNCiAgICAgICAgIHR3ZWV0X2Z1bGxfdGV4dCA9IHN0cmlwV2hpdGVzcGFjZSh0d2VldF9mdWxsX3RleHQpLA0KICAgICAgICAgdHdlZXRfZnVsbF90ZXh0ID0gd29yZFN0ZW0odHdlZXRfZnVsbF90ZXh0KSkNCmBgYA0KDQpgYGB7cn0NCiMgQ2FsY3VsYXRlIGF2ZXJhZ2Ugc2VudGltZW50IGZvciBlYWNoIHN0YXRlDQpzdGF0ZV9zZW50aW1lbnQgPC0gQWxsX0NsZWFuZWRfVHdlZXRzICU+JQ0KICBncm91cF9ieSh1c2VyX2xvY2F0aW9uX3VzKSAlPiUNCiAgc3VtbWFyaXNlKGF2ZXJhZ2Vfc2VudGltZW50ID0gbWVhbihTZW50aW1lbnQsIG5hLnJtID0gVFJVRSkpICU+JQ0KIyBBcnJhbmdlIGRhdGEgaW4gZGVzY2VuZGluZyBvcmRlciBvZiBhdmVyYWdlX3NlbnRpbWVudA0KICBhcnJhbmdlKGRlc2MoYXZlcmFnZV9zZW50aW1lbnQpKQ0KYGBgDQoNCmBgYHtyfQ0KIyBUb3AgNSBzdGF0ZXMgd2l0aCB0aGUgaGlnaGVzdCBhdmVyYWdlIHNlbnRpbWVudA0KdG9wXzVfc3RhdGVzIDwtIHN0YXRlX3NlbnRpbWVudCAlPiUNCiAgc2xpY2VfbWF4KG9yZGVyX2J5ID0gYXZlcmFnZV9zZW50aW1lbnQsIG4gPSA1KQ0KcHJpbnQodG9wXzVfc3RhdGVzLCAiVG9wIDUgU3RhdGVzIGJ5IEF2ZXJhZ2UgU2VudGltZW50IikNCg0KIyBCb3R0b20gNSBzdGF0ZXMgd2l0aCB0aGUgbG93ZXN0IGF2ZXJhZ2Ugc2VudGltZW50DQpib3R0b21fNV9zdGF0ZXMgPC0gc3RhdGVfc2VudGltZW50ICU+JQ0KICBzbGljZV9taW4ob3JkZXJfYnkgPSBhdmVyYWdlX3NlbnRpbWVudCwgbiA9IDUpDQpwcmludChib3R0b21fNV9zdGF0ZXMsICJCb3R0b20gNSBTdGF0ZXMgYnkgQXZlcmFnZSBTZW50aW1lbnQiKQ0KYGBgDQpgYGB7cn0NCiMgTGV0IHVzIGNvcnJlbGF0ZSB3aXRoIHRoZSBzYWxlcyBmb3IgTmlrZSBhY29yc3MgTm9ydGggQW1lcmljYSB3aXRoIHRoZSBzYWxlcyBkYXRhc2V0IGZvciAyMDIwLTIwMjENCg0KTmlrZV9zYWxlc19kYXRhIDwtIHJlYWQuY3N2KCJDOi9Vc2Vycy85MTk5Mi9PbmVEcml2ZS9EZXNrdG9wL0dHVS9SIHByb2plY3RzL05pa2VfU2FsZXNfVVMuY3N2IiwgaGVhZGVyID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCiMgRGVmaW5lIHRoZSBsaXN0IG9mIHN0YXRlcyB5b3UncmUgaW50ZXJlc3RlZCBpbg0KdG9wXzVfc3RhdGVzX3NhbGVzIDwtIGMoIk1vbnRhbmEiLCAiTm9ydGggRGFrb3RhIiwgIld5b21pbmciLCAiRGVsYXdhcmUiLCAiTWlzc291cmkiKQ0KDQojIFN1bW1hcml6ZSB0aGUgZmluYWwgc2FsZXMgY291bnQgZm9yIHRoZSBzZWxlY3RlZCBzdGF0ZXMNCmZpbmFsX3NhbGVzX3RvcF9zZWxlY3RlZF9zdGF0ZXMgPC0gTmlrZV9zYWxlc19kYXRhICU+JQ0KICBmaWx0ZXIoU3RhdGUgJWluJSB0b3BfNV9zdGF0ZXNfc2FsZXMpICU+JQ0KICBncm91cF9ieShTdGF0ZSkgJT4lDQogIHN1bW1hcmlzZShUb3RhbFNhbGVzQ291bnQgPSBzdW0oVG90YWwuU2FsZXMsIG5hLnJtID0gVFJVRSkpICU+JQ0KICB1bmdyb3VwKCkgIyBPcHRpb25hbCwgdG8gcmVtb3ZlIHRoZSBncm91cGluZw0KICANCiMgRGlzcGxheSB0aGUgcmVzdWx0DQpwcmludChmaW5hbF9zYWxlc190b3Bfc2VsZWN0ZWRfc3RhdGVzKQ0KYGBgDQoNCmBgYHtyfQ0KIyBEZWZpbmUgdGhlIGxpc3Qgb2Ygc3RhdGVzIHlvdSdyZSBpbnRlcmVzdGVkIGluDQpib3R0b21fNV9zdGF0ZXNfc2FsZXMgPC0gYygiT2tsYWhvbWEiLCAiV2VzdCBWaXJnaW5pYSIsICJBbGFza2EiLCAiTmVicmFza2EiLCAiTWlzc2lzc2lwcGkiKQ0KDQojIFN1bW1hcml6ZSB0aGUgZmluYWwgc2FsZXMgY291bnQgZm9yIHRoZSBzZWxlY3RlZCBzdGF0ZXMNCmZpbmFsX3NhbGVzX2JvdHRvbV9zZWxlY3RlZF9zdGF0ZXMgPC0gTmlrZV9zYWxlc19kYXRhICU+JQ0KICBmaWx0ZXIoU3RhdGUgJWluJSBib3R0b21fNV9zdGF0ZXNfc2FsZXMpICU+JQ0KICBncm91cF9ieShTdGF0ZSkgJT4lDQogIHN1bW1hcmlzZShUb3RhbFNhbGVzQ291bnQgPSBzdW0oVG90YWwuU2FsZXMsIG5hLnJtID0gVFJVRSkpICU+JQ0KICB1bmdyb3VwKCkgIyBPcHRpb25hbCwgdG8gcmVtb3ZlIHRoZSBncm91cGluZw0KDQojIERpc3BsYXkgdGhlIHJlc3VsdA0KcHJpbnQoZmluYWxfc2FsZXNfYm90dG9tX3NlbGVjdGVkX3N0YXRlcykNCmBgYA0KYGBge3J9DQojIG5vcm1hbGl6ZSBzZW50aW1lbnQgc2NvcmUNCkFsbF9DbGVhbmVkX1R3ZWV0cyA8LSBBbGxfQ2xlYW5lZF9Ud2VldHMgJT4lDQogIG11dGF0ZShOb3JtYWxpemVkX1N5dXpoZXQgPSBzaWduKFNlbnRpbWVudCkpDQpgYGANCg0KDQpgYGB7cn0NCiMgQXBwbHkgdGhlIGZ1bmN0aW9uIHRvIHBvc2l0aXZlIGFuZCBuZWdhdGl2ZSB0d2VldHMNCnBvc2l0aXZlX3R3ZWV0cyA8LSBBbGxfQ2xlYW5lZF9Ud2VldHNbQWxsX0NsZWFuZWRfVHdlZXRzJE5vcm1hbGl6ZWRfU3l1emhldCA+IDAsIF0NCm5lZ2F0aXZlX3R3ZWV0cyA8LSBBbGxfQ2xlYW5lZF9Ud2VldHNbQWxsX0NsZWFuZWRfVHdlZXRzJE5vcm1hbGl6ZWRfU3l1emhldCA8IDAsIF0NCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQoNCiMgRm9yIFBvc2l0aXZlIFR3ZWV0cw0KdG9wXzVfcG9zaXRpdmVfc3RhdGVzIDwtIHBvc2l0aXZlX3R3ZWV0cyAlPiUNCiAgZ3JvdXBfYnkodXNlcl9sb2NhdGlvbl91cykgJT4lDQogIHN1bW1hcmlzZShQb3NpdGl2ZVR3ZWV0Q291bnQgPSBuKCkpICU+JQ0KICBhcnJhbmdlKGRlc2MoUG9zaXRpdmVUd2VldENvdW50KSkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDUpDQoNCiMgRm9yIE5lZ2F0aXZlIFR3ZWV0cw0KdG9wXzVfbmVnYXRpdmVfc3RhdGVzIDwtIG5lZ2F0aXZlX3R3ZWV0cyAlPiUNCiAgZ3JvdXBfYnkodXNlcl9sb2NhdGlvbl91cykgJT4lDQogIHN1bW1hcmlzZShOZWdhdGl2ZVR3ZWV0Q291bnQgPSBuKCkpICU+JQ0KICBhcnJhbmdlKGRlc2MoTmVnYXRpdmVUd2VldENvdW50KSkgJT4lDQogIHNsaWNlX2hlYWQobiA9IDUpDQpgYGANCg0KYGBge3J9DQojIFByaW50IHRoZSByZXN1bHRzDQpwcmludCgiVG9wIDUgU3RhdGVzIHdpdGggSGlnaGVzdCBQb3NpdGl2ZSBUd2VldHM6IikNCnByaW50KHRvcF81X3Bvc2l0aXZlX3N0YXRlcykNCg0KcHJpbnQoIlRvcCA1IFN0YXRlcyB3aXRoIEhpZ2hlc3QgTmVnYXRpdmUgVHdlZXRzOiIpDQpwcmludCh0b3BfNV9uZWdhdGl2ZV9zdGF0ZXMpDQpgYGANCmBgYHtyfQ0KIyBTdG9yZSB0aGUgc3RhdGVzIGluIHRvcF81X3Bvc2l0aXZlX3N0YXRlcyBhbmQgdG9wXzVfbmVnYXRpdmVfc3RhdGVzIGRhdGEgZnJhbWVzDQp0b3BfNV9wb3NpdGl2ZV9zdGF0ZXNfbGlzdCA8LSB0b3BfNV9wb3NpdGl2ZV9zdGF0ZXMkdXNlcl9sb2NhdGlvbl91cw0KdG9wXzVfbmVnYXRpdmVfc3RhdGVzX2xpc3QgPC0gdG9wXzVfbmVnYXRpdmVfc3RhdGVzJHVzZXJfbG9jYXRpb25fdXMNCg0KIyBGaWx0ZXIgdHdlZXRzIGZyb20gdGhlc2UgdG9wIDUgc3RhdGVzDQpwb3NpdGl2ZV90d2VldHNfdG9wNSA8LSBwb3NpdGl2ZV90d2VldHMgJT4lDQogIGZpbHRlcih1c2VyX2xvY2F0aW9uX3VzICVpbiUgdG9wXzVfcG9zaXRpdmVfc3RhdGVzX2xpc3QpDQoNCm5lZ2F0aXZlX3R3ZWV0c190b3A1IDwtIG5lZ2F0aXZlX3R3ZWV0cyAlPiUNCiAgZmlsdGVyKHVzZXJfbG9jYXRpb25fdXMgJWluJSB0b3BfNV9uZWdhdGl2ZV9zdGF0ZXNfbGlzdCkNCmBgYA0KDQpgYGB7cn0NCmxpYnJhcnkodGlkeXRleHQpDQoNCiMgVG9rZW5pemUgcG9zaXRpdmUgdHdlZXRzIGFuZCBjYWxjdWxhdGUgd29yZCBmcmVxdWVuY2llcw0KcG9zaXRpdmVfd29yZF9mcmVxIDwtIHBvc2l0aXZlX3R3ZWV0c190b3A1ICU+JQ0KICB1bm5lc3RfdG9rZW5zKHdvcmQsIHR3ZWV0X2Z1bGxfdGV4dCkgJT4lDQogIGNvdW50KHdvcmQsIHNvcnQgPSBUUlVFKQ0KDQojIFRva2VuaXplIG5lZ2F0aXZlIHR3ZWV0cyBhbmQgY2FsY3VsYXRlIHdvcmQgZnJlcXVlbmNpZXMNCm5lZ2F0aXZlX3dvcmRfZnJlcSA8LSBuZWdhdGl2ZV90d2VldHNfdG9wNSAlPiUNCiAgdW5uZXN0X3Rva2Vucyh3b3JkLCB0d2VldF9mdWxsX3RleHQpICU+JQ0KICBjb3VudCh3b3JkLCBzb3J0ID0gVFJVRSkNCmBgYA0KDQpgYGB7cn0NCmRhdGEoInN0b3Bfd29yZHMiKQ0KDQpwb3NpdGl2ZV93b3JkX2ZyZXEgPC0gcG9zaXRpdmVfd29yZF9mcmVxICU+JQ0KICBhbnRpX2pvaW4oc3RvcF93b3JkcywgYnkgPSAid29yZCIpDQoNCm5lZ2F0aXZlX3dvcmRfZnJlcSA8LSBuZWdhdGl2ZV93b3JkX2ZyZXEgJT4lDQogIGFudGlfam9pbihzdG9wX3dvcmRzLCBieSA9ICJ3b3JkIikNCmBgYA0KDQpgYGB7cn0NCiMgQWRqdXN0IE4gYXMgbmVlZGVkDQpOIDwtIDEwDQoNCmhlYWQocG9zaXRpdmVfd29yZF9mcmVxLCBOKQ0KaGVhZChuZWdhdGl2ZV93b3JkX2ZyZXEsIE4pDQpgYGANCg0KYGBge3J9DQpsaWJyYXJ5KGRwbHlyKQ0KDQojIEFzc3VtaW5nIE4gPSAxMA0KTiA8LSAxMA0KDQp0b3BfcG9zaXRpdmVfd29yZF9mcmVxIDwtIHBvc2l0aXZlX3dvcmRfZnJlcSAlPiUNCiAgaGVhZChOKQ0KDQp0b3BfbmVnYXRpdmVfd29yZF9mcmVxIDwtIG5lZ2F0aXZlX3dvcmRfZnJlcSAlPiUNCiAgaGVhZChOKQ0KYGBgDQoNCg0KYGBge3J9DQpsaWJyYXJ5KGdncGxvdDIpDQoNCiMgUGxvdCBmb3IgcG9zaXRpdmUgd29yZCBmcmVxdWVuY2llcw0KZ2dwbG90KHRvcF9wb3NpdGl2ZV93b3JkX2ZyZXEsIGFlcyh4ID0gcmVvcmRlcih3b3JkLCBuKSwgeSA9IG4pKSArDQogIGdlb21fY29sKGZpbGwgPSAiZG9kZ2VyYmx1ZSIpICsNCiAgZ2VvbV90ZXh0KGFlcyhsYWJlbCA9IG4pLCBwb3NpdGlvbiA9IHBvc2l0aW9uX2RvZGdlKHdpZHRoID0gMC45KSwgdmp1c3QgPSAtMC4yNSwgc2l6ZSA9IDMuNSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHRpdGxlID0gIlRvcCAxMCBXb3JkIEZyZXF1ZW5jaWVzIGluIFBvc2l0aXZlIFR3ZWV0cyIsDQogICAgICAgeCA9ICJXb3JkIiwNCiAgICAgICB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQoNCiMgUGxvdCBmb3IgbmVnYXRpdmUgd29yZCBmcmVxdWVuY2llcw0KZ2dwbG90KHRvcF9uZWdhdGl2ZV93b3JkX2ZyZXEsIGFlcyh4ID0gcmVvcmRlcih3b3JkLCBuKSwgeSA9IG4pKSArDQogIGdlb21fY29sKGZpbGwgPSAiZmlyZWJyaWNrIikgKw0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbiksIHBvc2l0aW9uID0gcG9zaXRpb25fZG9kZ2Uod2lkdGggPSAwLjkpLCB2anVzdCA9IC0wLjI1LCBzaXplID0gMy41KSArICAgIA0KICBjb29yZF9mbGlwKCkgKw0KICBsYWJzKHRpdGxlID0gIlRvcCAxMCBXb3JkIEZyZXF1ZW5jaWVzIGluIE5lZ2F0aXZlIFR3ZWV0cyIsDQogICAgICAgeCA9ICJXb3JkIiwNCiAgICAgICB5ID0gIkZyZXF1ZW5jeSIpICsNCiAgdGhlbWVfbWluaW1hbCgpDQpgYGANCg0K